import router, { asyncRoutes, constantRoutes } from "@/router";
import store from "./store";
import { Message } from "element-ui";
import NProgress from "nprogress"; // progress bar
import "nprogress/nprogress.css"; // progress bar style
import { getToken } from "@/utils/auth"; // get token from cookie
import getPageTitle from "@/utils/get-page-title";
import { currentRole } from "@/api/user";


NProgress.configure({ showSpinner: false }); // NProgress Configuration

const whiteList = ["login", "403","distributeLogin"]; // no redirect whitelist

router.beforeEach(async (to, from, next) => {
    // store.state.user.routes = asyncRoutes;
    // return next();

    NProgress.start();
    // set page title
    document.title = getPageTitle(to.meta.title);
    const hasToken = getToken();


    if (hasToken) {
        if (to.name === "login") {
            next({ path: "/" });
            NProgress.done();
        } else if (to.name === "403") {
            next();
            NProgress.done();
        } else {
            if (!store.state.currentUser) {
                const currentUser = await store.dispatch("user/getInfo");
                store.state.currentUser = currentUser;
            }

            const hasRoles = store.state.user.roles;

            if (hasRoles) {

                if (to.meta.role === false) {
                    next({ path: "/401" });
                } else {

                    next();
                }
            } else {
                try {
                    const roles = await currentRole();
                    store.state.user.roles = roles;
                    generateRoutes(roles);
                    next({ ...to, replace: true });
                } catch (error) {
                    console.error(error);
                    await store.dispatch("user/resetToken");
                    Message.error("账号异常，请重新登录");
                    next(`/login?redirect=${to.path}`);
                    NProgress.done();
                }
            }
        }
    } else {
        if (whiteList.includes(to.name)) {
            next();
        } else {
            next(`/login?redirect=${to.path}`);
            NProgress.done();
        }
    }
});

function hasPermission(roles, route) {
    if (route.meta && route.meta.roles) {
        return roles.some(role => route.meta.roles.includes(role));
    } else {
        return true;
    }
}

function filterAsyncRoutes(routes, roles, vl) {
    const res = [];
    routes.forEach(route => {
        const tmp = { ...route };
        if (vl !== undefined) {
            tmp.meta = {
                ...(tmp.meta || {}),
                role: vl
            };
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles, vl);
            }
        } else if (hasPermission(roles, tmp)) {
            tmp.meta = {
                ...(tmp.meta || {}),
                role: true
            };
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles);
            }
        } else {
            tmp.meta = {
                ...(tmp.meta || {}),
                role: false
            };
            if (tmp.children) {
                tmp.children = filterAsyncRoutes(tmp.children, roles, false);
            }
        }
        res.push(tmp);
    });
    return res;
}

function generateRoutes(roles) {
    let accessedRoutes = [];

    if (roles.includes("maxAdmin")) {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles, true);

    } else {
        accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
    }


    router.addRoutes(accessedRoutes);
    store.state.user.routes = accessedRoutes;

}

router.afterEach(() => {
    NProgress.done();
});
